﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mshtml;
using SHDocVw;
using System.Text.RegularExpressions;

namespace Password_Changer
{
    public static class HTMLDocumentExtensions
    {
        public static HTMLInputTextElement GetButtonByText(this HTMLDocument document, string text)
        {
            IHTMLElementCollection inputs = document.getElementsByTagName("input");
            IEnumerable<HTMLInputTextElement> items = from i in inputs.OfType<HTMLInputTextElement>()
                                                      where i.value == text
                                                      select i;
            return items.Take(1).Single();
        }

        public static IEnumerable<HTMLInputTextElement> GetElementByLabel(this HTMLDocument doc, string text)
        {
            IEnumerable<HTMLLabelElement> labels = getElementsByTagName2<HTMLLabelElement>(doc, "label");

            IEnumerable<HTMLLabelElement> selectedLabels = from l in labels
                                                           where l.innerText == text
                                                           select l;
            List<HTMLInputTextElement> textFields = new List<HTMLInputTextElement>();

            foreach (IHTMLLabelElement label in selectedLabels)
            {
                string labelFor = label.htmlFor;
                if (labelFor != null && labelFor.Length > 0)
                {
                    object textField = doc.getElementById(labelFor);
                    if (textField != null && textField is HTMLInputElement)
                    {
                        textFields.Add((HTMLInputTextElement)textField);
                    }
                }
            }
            return textFields.AsEnumerable<HTMLInputTextElement>();
        }

        public static T getElementById<T>(this HTMLDocument document, string id)
        {
            return (T)document.getElementById(id);
        }

        public static IEnumerable<T> getElementsByTagName2<T>(this HTMLDocument document, string id)
        {
            return document.getElementsByTagName(id).OfType<T>();
        }

        /// <summary>
        /// Verifica si la página actual coinicde con la expresión regular dada.
        /// </summary>
        /// <param name="regex"></param>
        /// <returns></returns>
        public static  Boolean URLMatches( this HTMLDocument document, string regex)
        {
            return Regex.IsMatch(document.url, regex);
        }

        public static Boolean ContainsElement(this HTMLDocument document, string id){
            return document.getElementById(id) != null;
        }


        public static Boolean ContainsAllElementIDs(this HTMLDocument doc, params string[] ids) {
            foreach (string id  in ids){
                if (!doc.ContainsElement(id))
                    return false;
            }
            return true;
        }

        public static Boolean ContainsAllElementIDs(this HTMLDocument doc, IEnumerable<string> ids)
        {
            foreach (string id in ids)
            {
                if (!doc.ContainsElement(id))
                    return false;
            }
            return true;
        }

        public static string GetLanguage(this HTMLDocument doc) {
            IHTMLElementCollection element = doc.getElementsByTagName("html");
            if(element.length == 1)
            return ((HTMLHtmlElement)element.item(0)).getAttribute("lang", 2);
            return null;
        }

        public static HTMLInputTextElement FindInputElement( this HTMLDocument doc, InputElement element) {
            HTMLInputTextElement inputElement = null;
            if (!string.IsNullOrEmpty(element.ID))
            {
                inputElement = getElementById<HTMLInputTextElement>(doc, element.ID);
            }
            else if (!string.IsNullOrEmpty(element.Label))
            {
                inputElement = GetElementByLabel(doc, element.Label). Take(1).Single();
            }
            return inputElement;
        }

        public static HTMLFormElement FindFormByInputId(this HTMLDocument doc, string inputId) {
            IHTMLElement input = (IHTMLElement)doc.FindInputElement(new InputElement() { ID = inputId });
            HTMLFormElement form = input.getNearestParent<HTMLFormElement>();
            return form;
        }

        public static T getNearestParent<T>(this IHTMLElement element)
        {
            IHTMLElement parent = element.parentElement;
            while ((parent != null) && !(parent is T))
            {
                parent = parent.parentElement;
            }
            return (T)parent;
        }
    }



    public static class IEExtensions
    {

        private static object o = null;
        public static void Navigate3(this InternetExplorer me, string url)
        {
            object _url = url;
            me.Navigate2(ref _url, ref o, ref o, ref o, ref o);
        }
    }
}
